package juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @ClassName : ABADemo
 * @Author : hyy
 * @Date: 2020-03-11
 */
public class ABADemo {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger atomicInteger = new AtomicInteger(100);
        // new AtomicStampedReference(var1, var2) var1:原子引用的初始值，var2:起始版本戳
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,0);
        System.out.println("===========ABA问题展示=========");
        new Thread(()->{
            try {
                // 线程休眠1秒，保证t2线程拷贝到的工作内存中的变量时最初的变量
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // true
            System.out.println(atomicInteger.compareAndSet(100, 101));
            // true
            System.out.println(atomicInteger.compareAndSet(101, 100));
            System.out.println(atomicInteger.compareAndSet(101, 100));
        },"t1").start();

        new Thread(()->{
            // 线程休眠2秒钟，保证上面的ABA操作完成
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 虽然上面修改了atomicInteger的值，但T1线程最终还是将atomicInteger的值修改到了100，和t2线程在启动之初拷贝的值相同
            // true
            System.out.println(atomicInteger.compareAndSet(100, 102));
        },"t1").start();

        TimeUnit.SECONDS.sleep(3);

        System.out.println("==========ABA问题解决===========");
        new Thread(()->{
            try {
                // 线程休眠1秒，保证t2线程拷贝到的工作内存中的变量时最初的变量
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // true
            System.out.println(Thread.currentThread().getName()+"\t 第一次修改前版本戳："+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(100, 101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1));
            // true
            System.out.println(Thread.currentThread().getName()+"\t 第二次修改前版本戳："+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(101, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1));
        },"t3").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            try {
                // 线程休眠2秒钟，保证上面的ABA操作完成
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // true 虽然上面的t3 线程最终将值修改回了100 但是版本戳已经发生了改变
            //System.out.println(Thread.currentThread().getName()+"\t 第一次修改前版本戳："+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(100, 101, stamp,atomicStampedReference.getStamp()+1));
        },"t4").start();


    }
}
